//
// Created by Administrator on 2022/3/13.
//

#include "sched/sched_sequential.h"
#include "sched/sched_entry.h"

static TsSchedContainer* Push(uint16_t nowPc, TsInstance instance) {
    TsSchedContainer* container = TS_SCHED_STACK_Push(&instance->stack);
    container->container_pc = nowPc;
    container->now_pc = nowPc + 1;
    return container;
}

static TsStatus Sched(TsInstance instance, TsSchedContainer* currSched) {
    TsSched* containerAction = &(instance->trans[currSched->container_pc]);
    for (; (currSched->now_pc - currSched->container_pc) < containerAction->numOfChildren;) {
        TsSched* child = &instance->trans[currSched->now_pc];
        TsStatus status = TS_SCHED_StartAction(currSched->now_pc, instance);
        if (status != TS_SUCCESS) {
            instance->failStatus = status;
            return status;
        }

        if (!TS_SCHED_STACK_IsTop(currSched, &instance->stack)) {
            return TS_SUCCESS;
        }

        currSched->now_pc += child->numOfChildren;
    }

    // sched end
    TS_SCHED_STACK_Pop(&instance->stack);
    return TS_SUCCESS;
}

DEF_SCHED_START_FUNC(TS_SCHED_SEQUENTIAL) {
    return Sched(instance, Push(pc, instance));
}

DEF_SCHED_HANDLE_EVENT_FUNC(TS_SCHED_SEQUENTIAL) {
    TsSchedContainer* child = container + 1;
    TsStatus status = TS_SCHED_HandleEvent(child, instance);
    if (status != TS_SUCCESS) {
        instance->failStatus = status;
        return status;
    }
    container->now_pc += instance->trans[child->container_pc].numOfChildren;
    return Sched(instance, container);
}